#include <stdarg.h>
#include <stdint.h>
#include "uart.h"

static void outc(char c) { uart_putc(c); }

static void outs(const char *s) {
    if (!s) { outs("(null)"); return; }
    while (*s) outc(*s++);
}

// 将无符号数按 base(2..16) 输出
static void out_u64_base(uint64_t x, unsigned base) {
    static const char digits[] = "0123456789abcdef";
    char buf[32];
    int i = 0;

    if (x == 0) {
        outc('0');
        return;
    }
    while (x) {
        buf[i++] = digits[x % base];
        x /= base;
    }
    while (i) outc(buf[--i]);
}

// 安全处理有符号数（避免 -LLONG_MIN 溢出）
static void out_s64_base(int64_t v, unsigned base) {
    if (v < 0) {
        outc('-');
        // 两补：把 v 视为无符号，再取绝对值
        uint64_t x = (uint64_t)v;
        x = (~x) + 1; // 绝对值
        out_u64_base(x, base);
    } else {
        out_u64_base((uint64_t)v, base);
    }
}

int printf(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);

    for (const char *p = fmt; *p; ++p) {
        if (*p != '%') { outc(*p); continue; }
        ++p;
        switch (*p) {
        case 'd': { // int (按 64 位扩展输出)
            int v = va_arg(ap, int);
            out_s64_base((int64_t)v, 10);
        } break;
        case 'x': { // unsigned int → 16进制
            unsigned v = va_arg(ap, unsigned);
            out_u64_base((uint64_t)v, 16);
        } break;
        case 'p': { // 指针
            uintptr_t v = (uintptr_t)va_arg(ap, void *);
            outs("0x");
            out_u64_base((uint64_t)v, 16);
        } break;
        case 's': {
            const char *s = va_arg(ap, const char *);
            outs(s);
        } break;
        case 'c': {
            int ch = va_arg(ap, int);
            outc((char)ch);
        } break;
        case '%': outc('%'); break;
        default:  // 未知格式：原样回显
            outc('%'); outc(*p);
            break;
        }
    }

    va_end(ap);
    return 0;
}

/* 基本测试 */
void test_printf_basic(void) {
    printf("Testing integer: %d\n", 42);
    printf("Testing negative: %d\n", -123);
    printf("Testing zero: %d\n", 0);
    printf("Testing hex: 0x%x\n", 0xABC);
    printf("Testing string: %s\n", "Hello");
    printf("Testing char: %c\n", 'X');
    printf("Testing percent: %%\n");
}

/* 边界测试 */
void test_printf_edge_cases(void) {
    printf("INT_MAX: %d\n", 2147483647);
    printf("INT_MIN: %d\n", (int)0x80000000u); // 演示负界
    printf("NULL string: %s\n", (char*)0);
    printf("Empty string: %s\n", "");
}